package com.kk.crowd.handler;

import com.kk.crowd.api.MysqlRemoteService;
import com.kk.crowd.api.RedisRemoteService;
import com.kk.crowd.config.ShortMessageProperties;
import com.kk.crowd.constant.CrowdConstant;
import com.kk.crowd.entity.po.MemberPO;
import com.kk.crowd.entity.vo.MemberLoginVO;
import com.kk.crowd.entity.vo.MemberVO;
import com.kk.crowd.util.CrowdUtil;
import com.kk.crowd.util.ResultEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberHandler {

    @Autowired
    private ShortMessageProperties smp;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MysqlRemoteService mysqlRemoteService;

    // 退出
    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){
        session.invalidate ();
        return "redirect:http://www.crowd.com/";
    }

    // 登录
    @RequestMapping("auth/member/do/login")
    public String login(@RequestParam("loginacct") String loginacct,
                        @RequestParam("userpswd") String userpswd,
                        ModelMap modelMap,
                        HttpSession session){

        // 1.验证是否存在，并作出相应返回
        ResultEntity<MemberPO> resultEntity = mysqlRemoteService.getMemberPOByLoginAcctRemote (loginacct);
        if (ResultEntity.FAILED.equals (resultEntity.getResult ())){
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage ());
            return "member-login";
        }

        MemberPO memberPO = resultEntity.getData ( );

        if (memberPO==null){
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        // 2.比较密码
        String userpassDataBase = memberPO.getUserpswd ( );
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder ( );
        boolean resultMatches = passwordEncoder.matches ( userpswd,userpassDataBase);
        if (!resultMatches){
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        // 3.如果密码相同，创建MemberLoginVO 存入session域中
        MemberLoginVO memberLoginVO = new MemberLoginVO (memberPO.getId ( ), memberPO.getUsername ( ), memberPO.getEmail ( ));
        session.setAttribute (CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);

        // 这边指定地址 127.0.0.1(www.crowd.com) 指向默认的 80 端口
        // 注意这边需要模拟域名，否则 127.0.0.1 不能重定向
        // 保证和 zuul 在同一个网站，保证cookie ，session 同一共享
        return "redirect:http://www.crowd.com/auth/member/to/center/page";
    }

    // 注册
    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap) {

        // 1.获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum ( );
        // 2.拼接 redis 中存储的key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
        // 3.从 redis 读取 key 对应的 value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote (key);
        // 4.检查查询操作是否有效
        String result = resultEntity.getResult ( );
        if (ResultEntity.FAILED.equals (result)) {
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage ( ));
            return "member-reg";
        }
        String redisCode = resultEntity.getData ( );
        if (redisCode == null) {
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }

        // 5.如果从 redis 能够查询到value 则比较表单的验证码和redis的验证码
        String formCode = memberVO.getCode ( );
        if (!Objects.equals (formCode, redisCode)) {
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_INVALID);
            return "member-reg";
        }
        // 6.如果验证码一直，则从redis中删除(返回ResultEntity 都有可能失败，可以考虑分布式事务)
        ResultEntity<String> redisResultEntity= redisRemoteService.removeRedisKeyRemote (key);
        if (ResultEntity.FAILED.equals (redisResultEntity)){
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }
        // 7.执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder ( );

        String userpswd = memberVO.getUserpswd ( );
        String encode = passwordEncoder.encode (userpswd);
        memberVO.setUserpswd (encode);
        // 8.保存操作
        // ①创建空的MemberPO对象
        MemberPO memberPO = new MemberPO ( );
        // ②复制属性
        BeanUtils.copyProperties (memberVO,memberPO);
        // ③调用远程方法（可能导致失败）
        ResultEntity<String> saveMemberResultEntity = mysqlRemoteService.saveMember (memberPO);
        if (ResultEntity.FAILED.equals (saveMemberResultEntity.getResult ())){
            modelMap.addAttribute (CrowdConstant.ATTR_NAME_MESSAGE, saveMemberResultEntity.getMessage ());
            return "member-reg";
        }

        return "member-login";
    }

    // 发送短信
    @ResponseBody
    @RequestMapping("auth/memer/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum) {

        // 1.发送短信验证码到手机
        ResultEntity code = CrowdUtil.sendMeagess (smp.getHost ( ),
                smp.getPath ( ), smp.getAppcode ( ),
                smp.getSign ( ), smp.getSkin ( ), phoneNum);

        // 2.判断短信发送结果
        if (ResultEntity.SUCCESS.equals (code.getResult ( ))) {
            // 如果不为null 则是发送成功
            // 拼接一个用于redis 存储的 key
            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;

            // 调用远程接口存入 Redis
            ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeout (key, (String) code.getData ( ), 15, TimeUnit.MINUTES);

            // 判断结果(成功状态并且有值)
            if (ResultEntity.SUCCESS.equals (saveCodeResultEntity.getResult ( )) && saveCodeResultEntity.getData ( ) != null) {
                // 返回成功的结果
                return ResultEntity.successWithoutData ( );
            } else {
                // 失败返回本身
                return ResultEntity.failed ("发送失败！");
            }
        }
        return null;
    }
}
